package com.jikangjun.disk.file.service;

import com.jikangjun.disk.mybatis.entity.PtFileEntity;
import com.obs.services.ObsClient;
import com.obs.services.model.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileloServiceImpl implements FileloService {
    // 定义常量
    private static final int FILE_TYPE_FOLDER = 0;
    private static final int FILE_TYPE_FILE = 1;
    private static final String FILE_SEPARATOR = "/";

    @Value("${end.point}")
    private String endpoint = "";
    @Value("${ak}")
    private String ak = "";
    @Value("${sk}")
    private String sk = "";
    @Value("${bucket.name}")
    private String bucketName = "";

    private ObsClient obsClient = null;
    @Resource
    private FileService fileService;



    private ObsClient getObsClient() {
        if (this.obsClient == null) {
            this.obsClient = new ObsClient(ak, sk, endpoint);
        }
        return this.obsClient;
    }

    private Logger logger = LogManager.getLogger(this.getClass());


    @Override
    public void syncFileData() {
        ObjectListing list = getObsClient().listObjects(bucketName);
        List<ObsObject> listObjects = list.getObjects();
        PtFileEntity ptFileEntity = null;
        List<PtFileEntity> ptFileEntityList = new ArrayList<>();

        List<PtFileEntity> ptFileEntityList1 = fileService.queryFileListAll();
        String uuid = "";
        // 先创建所有文件/文件夹实体
        for (ObsObject obsObject : listObjects) {
            ptFileEntity = new PtFileEntity();
            ptFileEntityList.add(ptFileEntity);
            ptFileEntity.setParentUuid("-1"); // 默认为根目录
            ptFileEntity.setFilePath(obsObject.getObjectKey());
            uuid = UUID.randomUUID().toString();
            for(PtFileEntity ptFileEntityItem:ptFileEntityList1){
                uuid = uuid = ptFileEntityItem.getFileUuid();
                break;
            }
            ptFileEntity.setFileUuid(UUID.randomUUID().toString());
            ptFileEntity.setFileCapacity(obsObject.getMetadata().getContentLength());

            // 判断是否为文件夹并设置文件类型
            if (isFolder(obsObject.getObjectKey())) {
                ptFileEntity.setFileType(FILE_TYPE_FOLDER);
            } else {
                ptFileEntity.setFileType(FILE_TYPE_FILE); // 修复之前的逻辑错误
            }

            // 获取文件名称
            ptFileEntity.setFileName(getFileName(obsObject.getObjectKey()));
        }

        // 处理父节点关系
        for (PtFileEntity child : ptFileEntityList) {
            String childPath = child.getFilePath();
            String longestParentPath = "";
            String parentUuid = "-1"; // 默认根目录

            for (PtFileEntity parent : ptFileEntityList) {
                // 跳过自身和文件类型的父节点
                if (child.getFilePath().equals(parent.getFilePath()) ||
                        parent.getFileType() == FILE_TYPE_FILE) {
                    continue;
                }

                String parentPath = parent.getFilePath();
                // 子路径包含父路径，且是最长的匹配路径
                if (childPath.startsWith(parentPath) && parentPath.length() > longestParentPath.length()) {
                    longestParentPath = parentPath;
                    parentUuid = parent.getFileUuid();
                }
            }

            child.setParentUuid(parentUuid);
        }

        // 一次性保存所有数据
        logger.info("同步文件数据总数: {}", ptFileEntityList.size());
        fileService.saveFileInfo(ptFileEntityList);
    }

    @Override
    public void uploadFile(String parentId, String fileName, InputStream inputStream) {
        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String fileNameU = fileName;
        if (entity != null) {
            fileNameU = entity.getFilePath() + fileName;
        }

        getObsClient().putObject(bucketName, fileNameU, inputStream);
        syncFileData();
    }

    @Override
    public ResponseEntity<byte[]> downFile(String fileUuid) {
        PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
        String fileName = entity.getFileName();

        HttpHeaders headers = new HttpHeaders();
        try {
            // 仅添加中文文件名编码处理，不增加额外功能
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
            headers.setContentDispositionFormData("attachment", encodedFileName);
        } catch (UnsupportedEncodingException e) {
            logger.info("文件名编码失败", e);
            headers.setContentDispositionFormData("attachment", fileName);
        }

        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        ObsObject obsObject = getObsClient().getObject(bucketName, entity.getFilePath());
        InputStream inputStream = obsObject.getObjectContent();
        byte[] block = new byte[1024];
        int length = 0;

        byte[] fileByte = new byte[0];
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            while ((length = inputStream.read(block)) > 0) {
                byteArrayOutputStream.write(block, 0, length);
                byteArrayOutputStream.flush();
            }
            fileByte = byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            logger.info(e);
        } finally {
            try {
                inputStream.close(); // 补充关闭输入流，避免资源泄漏
            } catch (IOException e) {
                logger.info("输入流关闭失败", e);
            }
        }
        return new ResponseEntity<>(fileByte, headers, HttpStatus.CREATED);
    }


    @Override
    public String queryShareUrl(String fileUuid, Integer fileValidity) {
        try {
            PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
            if (entity == null) {
                logger.error("文件不存在: {}", fileUuid);
                return null;
            }
            
            TemporarySignatureRequest request = new TemporarySignatureRequest();
            request.setBucketName(bucketName);
            request.setObjectKey(entity.getFilePath());
            request.setRequestDate(new Date());
            request.setExpires(60*60*24*fileValidity);
            
            TemporarySignatureResponse signature = getObsClient().createTemporarySignature(request);
            String url = signature.getSignedUrl();
            
            logger.info("生成分享链接成功: fileUuid={}, validity={}天, url={}", fileUuid, fileValidity, url);
            return url;
        } catch (Exception e) {
            logger.error("生成分享链接失败: fileUuid={}, validity={}天", fileUuid, fileValidity, e);
            return null;
        }
    }

    /**
     * 判断是否为文件夹
     * @param filepath 文件路径
     * @return 是否为文件夹
     */
    private boolean isFolder(String filepath) {
        if (filepath != null && filepath.length() > 0) {
            String lastStr = filepath.substring(filepath.length() - 1);
            return FILE_SEPARATOR.equals(lastStr);
        }
        return false;
    }

    /**
     * 获取文件名称
     * @param filePath 文件路径
     * @return 文件名
     */
    private String getFileName(String filePath){
        String fileName = filePath;
        if(filePath.indexOf(FILE_SEPARATOR) != -1){
            String[] fileArray = filePath.split("/");
            if(isFolder(filePath)){
                fileName = fileArray[fileArray.length -1] + FILE_SEPARATOR;
            }else{
                fileName = fileArray[fileArray.length -1];
            }
        }

        return fileName;
    }

}